
import path, { resolve } from 'path';
import { readFileSync, unlinkSync, writeFileSync } from "fs";
import { runWorker, transformCSVToJSON } from "../../utils";
import { fitnessFunction } from "./mixIndicatorsTolerance.worker";
import { GeneticAlgorithm } from "../../trader/GeneticAlgorithm";

import { KLineDTO } from "../kline-history/KLineHistory.entity";
import SymbolFactorEntity from '../symbol-factor/SymbolFactor.entity';
import { fitnessStrategy } from './strategy.worker';


/**
 * 混合指标相似度训练
 */
export async function trainMixIndicatorsTolerance(vectors: SymbolFactorEntity[], history: KLineDTO[]) {
  if (vectors.length === 0) {
    console.error('vectors 为空');
    return;
  }

  const resultFilePath = path.resolve(__dirname, './result.json');
  writeFileSync(resultFilePath, '');
  
  if (history === undefined) {
    const historyStr = readFileSync(path.resolve(__dirname, './data.csv'), { encoding: 'utf-8' });
    try {
      unlinkSync(resultFilePath);
    } catch (error) {
      console.error(error)
    }
    history = transformCSVToJSON(historyStr);
  }

  const symbol = history[0].symbol;

  const ga = new GeneticAlgorithm({
    populationSize: 340,
    mutationRate: 0.1,
    crossoverRate: 0.8,
    generations: 40,
    parameterRanges: [
      [0.2, 3],

      [0.1, 3],
      [0.1, 2],
      [0.1, 2],

      [0.1, 3],
      [0.1, 2],
      [0.1, 2],

      [0.1, 3],
      [0.1, 2],
      [0.1, 2],
    ],
    parameterStep: 0.2,
    fitnessFunction: function(genes) {
      return runWorker<typeof fitnessFunction>(resolve(__dirname, './mixIndicatorsTolerance.worker.ts'), [0,0,0, ...genes], {
        workerData: {
          symbol: symbol,
          history,
          vectors,
          period: '4h'
        }
      })
    }
  });
  
  const result = await ga.run();
  console.log('geneticAlgorithmParams', result)
}


/**
 * 普通策略训练
 */
export async function trainStrategy(history: KLineDTO[]) {


  const resultFilePath = path.resolve(__dirname, './result_strategy.json');
  writeFileSync(resultFilePath, '');
  
  if (history === undefined) {
    const historyStr = readFileSync(path.resolve(__dirname, './data.csv'), { encoding: 'utf-8' });
    try {
      unlinkSync(resultFilePath);
    } catch (error) {
      console.error(error)
    }
    history = transformCSVToJSON(historyStr);
  }

  const symbol = history[0].symbol;

  const ga = new GeneticAlgorithm({
    populationSize: 350,
    mutationRate: 0.1,
    crossoverRate: 0.8,
    generations: 50,
    parameterRanges: [
      [-0.02, -0.3], // 1 buy_close_ma_target
      [0.02, 0.3], // 0 sell_close_ma_target
      [0.02, 0.4], // 2  buy_volume_rate_15m
      [0.02, 0.4], // 3  sell_volume_rate_15m 
      [0.01, 0.8], // 4  buy_exceptional_undulation_4h_target
      [0.01, 0.8], // 5  sell_exceptional_undulation_4h_target
    ],
    parameterStep: 0.01,
    fitnessFunction: function(genes) {
      return runWorker<typeof fitnessStrategy>(resolve(__dirname, './strategy.worker.ts'), genes, {
        workerData: {
          symbol: symbol,
          history,
          period: '15m'
        }
      })
    }
  });
  
  const result = await ga.run();
  console.log('geneticAlgorithmParams', result)
}
